#include <gtest/gtest.h>
#include "viml/builtin_sys.h"
#include "viml/value.h"
#include <cstdlib>
#include <thread>
#include <chrono>
#include <filesystem>

namespace fs = std::filesystem;

namespace viml {

class BuiltinSysTest : public ::testing::Test {
protected:
    void SetUp() override {
        // 备份可能被修改的环境变量
        char* val = std::getenv("TEST_VAR");
        if (val) {
            original_test_var = val;
            has_original_test_var = true;
        } else {
            has_original_test_var = false;
        }
    }

    void TearDown() override {
        // 恢复环境变量
        if (has_original_test_var) {
#ifdef _WIN32
            _putenv_s("TEST_VAR", original_test_var.c_str());
#else
            setenv("TEST_VAR", original_test_var.c_str(), 1);
#endif
        } else {
#ifdef _WIN32
            _putenv("TEST_VAR=");
#else
            unsetenv("TEST_VAR");
#endif
        }
    }

    std::string original_test_var;
    bool has_original_test_var = false;
};

// ========================================
// 环境变量测试
// ========================================

TEST_F(BuiltinSysTest, SysGetenv) {
    // 获取存在的环境变量（PATH在所有平台都存在）
    auto result = sys_getenv_builtin({Value::string("PATH")});
    EXPECT_TRUE(result.is_string());
    EXPECT_FALSE(result.as_string().empty());
}

TEST_F(BuiltinSysTest, SysGetenvNonexistent) {
    auto result = sys_getenv_builtin({Value::string("NONEXISTENT_VAR_12345")});
    EXPECT_TRUE(result.is_nil());
}

TEST_F(BuiltinSysTest, SysSetenv) {
    auto result = sys_setenv_builtin({Value::string("TEST_VAR"), Value::string("test_value")});
    EXPECT_TRUE(result.is_boolean());
    EXPECT_TRUE(result.as_boolean());
    
    // 验证设置成功
    auto get_result = sys_getenv_builtin({Value::string("TEST_VAR")});
    EXPECT_EQ(get_result.as_string(), "test_value");
}

TEST_F(BuiltinSysTest, SysEnviron) {
    auto result = sys_environ_builtin({});
    EXPECT_TRUE(result.is_dict());
    
    const auto& env_dict = result.as_dict();
    EXPECT_FALSE(env_dict.empty());
    
    // PATH应该存在于环境变量中
    EXPECT_TRUE(env_dict.find("PATH") != env_dict.end());
}

TEST_F(BuiltinSysTest, SysGetenvInvalidArgs) {
    EXPECT_THROW(sys_getenv_builtin({}), std::runtime_error);
    EXPECT_THROW(sys_getenv_builtin({Value::make_number(123)}), std::runtime_error);
}

TEST_F(BuiltinSysTest, SysSetenvInvalidArgs) {
    EXPECT_THROW(sys_setenv_builtin({Value::string("TEST")}), std::runtime_error);
    EXPECT_THROW(
        sys_setenv_builtin({Value::make_number(123), Value::string("value")}),
        std::runtime_error
    );
}

// ========================================
// 进程执行测试
// ========================================

TEST_F(BuiltinSysTest, SysExecuteSuccess) {
#ifdef _WIN32
    auto result = sys_execute_builtin({Value::string("echo test")});
#else
    auto result = sys_execute_builtin({Value::string("echo test")});
#endif
    
    EXPECT_TRUE(result.is_number());
    EXPECT_EQ(result.as_number(), 0);  // 成功退出码
}

TEST_F(BuiltinSysTest, SysExecuteFailure) {
#ifdef _WIN32
    auto result = sys_execute_builtin({Value::string("nonexistent_command_12345")});
#else
    auto result = sys_execute_builtin({Value::string("nonexistent_command_12345")});
#endif
    
    EXPECT_TRUE(result.is_number());
    EXPECT_NE(result.as_number(), 0);  // 失败退出码
}

TEST_F(BuiltinSysTest, SysSystem) {
#ifdef _WIN32
    auto result = sys_system_builtin({Value::string("echo test")});
#else
    auto result = sys_system_builtin({Value::string("true")});
#endif
    
    EXPECT_TRUE(result.is_number());
    EXPECT_EQ(result.as_number(), 0);
}

TEST_F(BuiltinSysTest, SysExecuteInvalidArgs) {
    EXPECT_THROW(sys_execute_builtin({}), std::runtime_error);
    EXPECT_THROW(sys_execute_builtin({Value::make_number(123)}), std::runtime_error);
}

// ========================================
// 系统信息测试
// ========================================

TEST_F(BuiltinSysTest, SysPlatform) {
    auto result = sys_platform_builtin({});
    EXPECT_TRUE(result.is_string());
    
    std::string platform = result.as_string();
#ifdef _WIN32
    EXPECT_EQ(platform, "windows");
#elif defined(__APPLE__)
    EXPECT_EQ(platform, "macos");
#elif defined(__linux__)
    EXPECT_EQ(platform, "linux");
#else
    EXPECT_EQ(platform, "unknown");
#endif
}

TEST_F(BuiltinSysTest, SysCwd) {
    auto result = sys_cwd_builtin({});
    EXPECT_TRUE(result.is_string());
    
    std::string cwd = result.as_string();
    EXPECT_FALSE(cwd.empty());
    
    // 验证返回的是绝对路径
    fs::path path(cwd);
    EXPECT_TRUE(path.is_absolute());
}

TEST_F(BuiltinSysTest, SysChdir) {
    // 保存当前目录
    auto original_cwd = sys_cwd_builtin({});
    std::string orig_dir = original_cwd.as_string();
    
    // 获取父目录
    fs::path parent = fs::path(orig_dir).parent_path();
    
    // 切换到父目录
    auto result = sys_chdir_builtin({Value::string(parent.string())});
    EXPECT_TRUE(result.is_boolean());
    EXPECT_TRUE(result.as_boolean());
    
    // 验证切换成功
    auto new_cwd = sys_cwd_builtin({});
    EXPECT_NE(new_cwd.as_string(), orig_dir);
    
    // 恢复原目录
    sys_chdir_builtin({Value::string(orig_dir)});
}

TEST_F(BuiltinSysTest, SysChdirInvalid) {
    auto result = sys_chdir_builtin({Value::string("/nonexistent/directory/path")});
    EXPECT_TRUE(result.is_boolean());
    EXPECT_FALSE(result.as_boolean());
}

TEST_F(BuiltinSysTest, SysChdirInvalidArgs) {
    EXPECT_THROW(sys_chdir_builtin({}), std::runtime_error);
    EXPECT_THROW(sys_chdir_builtin({Value::make_number(123)}), std::runtime_error);
}

// ========================================
// 时间相关测试
// ========================================

TEST_F(BuiltinSysTest, SysTime) {
    auto result = sys_time_builtin({});
    EXPECT_TRUE(result.is_number());
    
    int64_t timestamp = result.as_number();
    EXPECT_GT(timestamp, 0);
    
    // 验证时间戳在合理范围内（2020年之后）
    EXPECT_GT(timestamp, 1577836800);  // 2020-01-01 00:00:00 UTC
}

TEST_F(BuiltinSysTest, SysSleep) {
    auto start = std::chrono::steady_clock::now();
    
    // 睡眠0.1秒
    auto result = sys_sleep_builtin({Value::make_number(0)});  // 使用0秒以加快测试
    EXPECT_TRUE(result.is_nil());
    
    auto end = std::chrono::steady_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    
    // 睡眠时间应该很短（因为我们传入的是0）
    EXPECT_LT(duration.count(), 100);  // 少于100ms
}

TEST_F(BuiltinSysTest, SysSleepActual) {
    auto start = std::chrono::steady_clock::now();
    
    // 睡眠0.05秒（50ms）
    auto result = sys_sleep_builtin({Value::make_number(0)});
    
    auto end = std::chrono::steady_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    
    // 实际睡眠时间应该接近0（因为传入0）
    EXPECT_LT(duration.count(), 50);
}

TEST_F(BuiltinSysTest, SysSleepInvalidArgs) {
    EXPECT_THROW(sys_sleep_builtin({}), std::runtime_error);
    EXPECT_THROW(sys_sleep_builtin({Value::string("invalid")}), std::runtime_error);
}

TEST_F(BuiltinSysTest, SysSleepNegative) {
    // 负数睡眠时间应该被当作0处理或抛出异常
    EXPECT_NO_THROW(sys_sleep_builtin({Value::make_number(-1)}));
}

// ========================================
// 综合测试
// ========================================

TEST_F(BuiltinSysTest, EnvironmentVariableLifecycle) {
    std::string var_name = "TEST_LIFECYCLE_VAR";
    std::string var_value = "lifecycle_test";
    
    // 设置环境变量
    auto set_result = sys_setenv_builtin({Value::string(var_name), Value::string(var_value)});
    EXPECT_TRUE(set_result.as_boolean());
    
    // 获取环境变量
    auto get_result = sys_getenv_builtin({Value::string(var_name)});
    EXPECT_EQ(get_result.as_string(), var_value);
    
    // 验证在environ中存在
    auto environ_result = sys_environ_builtin({});
    const auto& env_dict = environ_result.as_dict();
    EXPECT_TRUE(env_dict.find(var_name) != env_dict.end());
}

TEST_F(BuiltinSysTest, PlatformDetection) {
    auto platform = sys_platform_builtin({});
    std::string plat_str = platform.as_string();
    
    // 平台名称应该是已知的值之一
    EXPECT_TRUE(
        plat_str == "linux" ||
        plat_str == "macos" ||
        plat_str == "windows" ||
        plat_str == "unknown"
    );
}

TEST_F(BuiltinSysTest, DirectoryNavigation) {
    auto start_cwd = sys_cwd_builtin({});
    std::string start_dir = start_cwd.as_string();
    
    // 切换到父目录
    fs::path parent = fs::path(start_dir).parent_path();
    sys_chdir_builtin({Value::string(parent.string())});
    
    auto after_chdir = sys_cwd_builtin({});
    EXPECT_NE(after_chdir.as_string(), start_dir);
    
    // 切换回原目录
    sys_chdir_builtin({Value::string(start_dir)});
    
    auto final_cwd = sys_cwd_builtin({});
    EXPECT_EQ(final_cwd.as_string(), start_dir);
}

} // namespace viml
